<!--
 * @Description:
 * @version:
 * @Author: mikeJang
 * @Date: 2021-06-15 11:50:29
 * @LastEditors: mikeJang
 * @LastEditTime: 2021-08-21 11:53:53
 * @FilePath: \YU_LIN_Frontend\src\components\SUpload.vue
-->
<template>
  <div class="upload-box" :class="inlineButton ? 'inline-button-upload' : ''">
    <a-upload
      :action="url"
      :name="name"
      :headers="headers"
      :data="requestData"
      :accept="accept"
      :count="count"
      :list-type="
        type !== 'file'
          ? type === 'picture'
            ? 'picture-card'
            : 'picture'
          : 'text'
      "
      :show-upload-list="showUploadList"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :remove="handleRemove"
      @preview="handlePreview"
      @change="handelChange"
    >
      <a-button
        v-if="!readOnly && fileList.length < count"
        :loading="loading"
        :disabled="disabled"
        :class="inlineButton ? 'inline-button' : ''"
      >
        <a-icon
          :type="loading ? 'loading' : 'upload'"
          :class="inlineButton ? 'inline-button-icon' : ''"
        />
      </a-button>
    </a-upload>

    <a-modal :visible="visible" :footer="null" @cancel="handleCancel">
      <div class="wrap">
        <img v-if="type === 'picture'" alt="previewImg" :src="imgUrl" />
        <audio v-else-if="type === 'audio'" controls muted>
          <source :src="audioUrl" type="audio/mpeg" />
          您的浏览器不支持 audio 元素。
        </audio>
        <video v-else-if="type === 'video'" controls muted>
          <!-- width="640"
          height="480" -->
          <source :src="videoUrl" type="video/mp4" />
          您的浏览器不支持 video 标签。
        </video>
      </div>
    </a-modal>
  </div>
</template>
<script>
import api from "@/util/api";

export default {
  props: {
    value: {
      type: String,
      default: ""
    },

    type: {
      required: true,
      type: String,
      default: "picture",
      validator: function (val) {
        return ["picture", "audio", "video", "file"].includes(val);
      }
    },
    count: {
      type: Number,
      default: 1,
      validator: function (val) {
        return val >= 1;
      }
    },
    pictureSize: {
      type: Number,
      default: 10
    },
    audioSize: {
      type: Number,
      default: 50
    },
    videoSize: {
      type: Number,
      default: 100
    },
    readOnly: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    inlineButton: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      url: '/api/'+this.$apiUrl+'-hzz/file/upload',
      name: "file",
      requestData: {},
      fileList: [
        // {
        //   uid: "-1",
        //   id:"",
        //   name: "xxx.png",
        //   status: "done",
        // response: '{"status": "success"}',
        //   thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',//只有type为audio或video时手动添加
        //   url: "https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png",
        // },
      ],
      loading: false,
      visible: false,
      imgUrl: "",
      audioUrl: "",
      videoUrl: "",
      needRender: true,
      headers: {
        Authorization:
          "Bearer " + getTemporaryInfo("access_token")
      }
    };
  },
  computed: {
    accept() {
      switch (this.type) {
        case "picture":
          return ".png, .jpg, .jpeg";
        case "video":
          return ".mp4";
        case "audio":
          return ".mp3";
        case "file":
          return ".pdf,.txt,.docx,.doc,.xls,.xlsx,.ppt,.pptx,.zip,.md";
        default:
          return ".*";
      }
    },
    showUploadList() {
      return {
        showPreviewIcon: true,
        showRemoveIcon: this.readOnly ? false : true
      };
    }
  },
  watch: {
    value: {
      handler: function (val) {
        if (val && this.needRender) {
          this.render(val);
        }
      },
      immediate: true
    }
  },
  methods: {
    getBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    },
    beforeUpload(file) {
      if (this.type === "picture") {
        const isPicture =
          file.type === "image/jpeg" || file.type === "image/png";
        if (!isPicture) {
          this.$message.error("只能上传图片文件!");
        }
        const pictureLimitSize = file.size / 1024 / 1024 < this.pictureSize;
        if (!pictureLimitSize) {
          this.$message.error(`图片不能大于${this.pictureSize}MB!`);
        }
        return isPicture && pictureLimitSize;
      } else if (this.type === "audio") {
        const isAudio = file.type === "audio/mpeg";
        if (!isAudio) {
          this.$message.error("只能上传音频文件!");
        }
        const audioLimitSize = file.size / 1024 / 1024 < this.audioSize;
        if (!audioLimitSize) {
          this.$message.error(`音频不能大于${this.audioSize}MB!`);
        }
        return isAudio && audioLimitSize;
      } else if (this.type === "video") {
        const isVideo = file.type === "video/mp4";
        if (!isVideo) {
          this.$message.error("只能上传视频文件!");
        }
        const videolimitSize = file.size / 1024 / 1024 < this.videoSize;
        if (!videolimitSize) {
          this.$message.error(`视频不能大于${this.videoSize}MB!`);
        }
        return isVideo && videolimitSize;
      }
    },
    async handlePreview(file) {
      switch (this.type) {
        case "picture":
          if (!file.url && !file.preview) {
            file.preview = await this.getBase64(file.originFileObj);
          }
          this.imgUrl = file.url || file.preview;
          this.visible = true;
          break;
        case "audio":
          if (!file.url && !file.preview) {
            file.preview = await this.getBase64(file.originFileObj);
          }
          this.audioUrl = file.url || file.preview;
          this.visible = true;
          break;
        case "video":
          if (!file.url && !file.preview) {
            file.preview = await this.getBase64(file.originFileObj);
          }
          this.videoUrl = file.url || file.preview;
          this.visible = true;
          break;
        case "file":
          window.open(file.url || file.preview);
          break;

        default:
          break;
      }
    },
    handleCancel() {
      this.visible = false;
    },
    async handelChange(info) {
      let fileList = [...info.fileList];
      fileList = await fileList.map(file => {
        if (file.response) {
          file.url =
            window.location.origin +
            `/api/${this.$apiUrl}-hzz/file/not-auth/download/${file.response.data}`;
          file.id = file.response.data;
          if (file.type === "audio/mpeg") {
            file.thumbUrl = require("@/assets/img/music.png");
          } else if (info.file.type === "video/mp4") {
            file.thumbUrl = require("@/assets/img/movie.png");
          }
        }
        return file;
      });
      this.fileList = fileList;
      switch (info.file.status) {
        case "uploading":
          this.loading = true;
          break;
        case "done":
          this.loading = false;

          break;
        case "error":
          this.loading = false;
          this.$message.error(info.file.name + "上传失败");
          info.file.url = "";
          break;
        default:
          break;
      }
      if (this.count === 1) {
        if (this.fileList.length > 0) {
          this.$emit("input", this.fileList[0].id);
        } else {
          this.$emit("input", "");
        }
        return;
      }
      if (this.fileList.length > 1) {
        const ids = [];
        this.fileList.forEach(item => {
          if (item.id) {
            ids.push(item.id);
          }
        });
        this.$emit("input", ids.join());
      } else {
        this.$emit("input", "");
      }
    },
    handleRemove(file) {
      this.fileList = this.fileList.filter(item => {
        return file.id !== item.id;
      });
      this.$emit("remove", file.id);
    },
    render(val) {
      if (val.indexOf(",") === -1) {
        api.get(`/api/${this.$apiUrl}-hzz/file/${val}`).then(res => {
          if (res) {
            const list = [];
            list.push({
              uid: "-uid-s",
              id: res.id,
              name: res.name,
              status: "done",
              url:
                window.location.origin +
                `/api/${this.$apiUrl}-hzz/file/not-auth/download/${res.id}`,
              thumbUrl:
                this.type === "audio"
                  ? require("@/assets/img/music.png")
                  : this.type === "video"
                  ? require("@/assets/img/movie.png")
                  : ""
            });
            this.fileList = list;
            this.needRender = false;
          }
        });
      } else {
        const list = [];
        api.get(`/api/${this.$apiUrl}-hzz/file/detail/${val}`).then(res => {
          if (res && res.length > 0) {
            res.map((item, index) => {
              list.push({
                uid: "-uid-a-" + index,
                id: item.id,
                name: item.name,
                status: "done",
                url:
                  window.location.origin +
                  `/api/${this.$apiUrl}-hzz/file/not-auth/download/${item.id}`,
                thumbUrl:
                  this.type === "audio"
                    ? require("@/assets/img/music.png")
                    : this.type === "video"
                    ? require("@/assets/img/movie.png")
                    : ""
              });
            });
          }
        });
        this.fileList = list;
        this.needRender = false;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.upload-box {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
}
.upload-box.inline-button-upload {
  display: inline-flex;
  width: auto;
}

::v-deep {
  .wrap {
    padding: 20px;
    max-height: 400px;

    img {
      width: 100%;
      height: auto;
    }
    video {
      width: 100%;
      height: auto;
    }
  }
  .ant-modal-body {
    padding: 8px;
  }

  .inline-button {
    width: 20px;
    height: 20px;
    padding: 0;
    background: #1890ff;
    border: none;
  }
  .inline-button-icon {
    color: white;
  }
}
</style>
